use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
use directories::ProjectDirs;
use config::{Config, File, Environment, ConfigError};
use anyhow::{Result, Context};

#[derive(Debug, Serialize, Deserialize, Clone)]
struct AppConfig {
    server: ServerConfig,
    logging: LoggingConfig,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
struct ServerConfig {
    host: String,
    port: u16,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
struct LoggingConfig {
    level: String,
    file: Option<PathBuf>,
}

struct ConfigManager {
    config: AppConfig,
    config_path: PathBuf,
}

impl ConfigManager {
    /// 获取配置目录路径并确保目录存在
    fn get_config_dir() -> Result<PathBuf> {
        let proj_dirs = ProjectDirs::from("hk", "topicon", "demo")
            .context("Could not determine project directory")?;
        
        let config_dir = proj_dirs.config_dir();
        if !config_dir.exists() {
            fs::create_dir_all(config_dir)
                .context("Failed to create config directory")?;
        }
        Ok(config_dir.join("config.toml"))
    }

    /// 加载配置（支持环境变量覆盖）
    fn load() -> Result<Self> {
        let config_path = Self::get_config_dir()?;
        
        let mut builder = Config::builder()
            .set_default("server.host", "li")?
            .set_default("server.port", 80)?
            .set_default("logging.level", "debug")?
            .set_default("logging.file", Option::<String>::None)?;

        // 添加配置文件（如果存在）
        if config_path.exists() {
            builder = builder.add_source(File::from(config_path.clone()));
        }

        // 添加环境变量支持
        builder = builder.add_source(
            Environment::with_prefix("APP")
                .separator("__")
                .ignore_empty(true)
        );

        let settings = builder.build()?;
        let config: AppConfig = settings.try_deserialize()?;

        Ok(Self { config, config_path })
    }

    /// 保存当前配置到文件
    fn save(&self) -> Result<()> {
        let toml = toml::to_string_pretty(&self.config)?;
        fs::write(&self.config_path, toml)
            .context("Failed to write config file")?;
        Ok(())
    }

    /// 获取当前配置的只读引用
    fn current(&self) -> &AppConfig {
        &self.config
    }

    /// 获取配置的可变引用（修改后需调用save保存）
    fn current_mut(&mut self) -> &mut AppConfig {
        &mut self.config
    }

    /// 更新整个配置
    fn update(&mut self, new_config: AppConfig) -> Result<()> {
        self.config = new_config;
        self.save()
    }
}

fn main() -> Result<()> {
    // 加载或创建配置
    let mut manager = ConfigManager::load()?;

    // 读取配置
    println!("Server: {}:{}", 
        manager.current().server.host, 
        manager.current().server.port);
    
    println!("Log level: {}", 
        manager.current().logging.level);

    // 修改单个配置项
    manager.current_mut().server.port = 9090;
    manager.save()?;
    println!("Updated port: {}", manager.current().server.port);

    // 完全替换配置
    let new_config = AppConfig {
        server: ServerConfig {
            host: "0.0.0.0".to_string(),
            port: 80,
        },
        logging: LoggingConfig {
            level: "debug".to_string(),
            file: Some("logs/app.log".into()),
        },
    };
    manager.update(new_config)?;
    println!("New config: {:?}", manager.current());

    Ok(())
}